package commons.ui.dialog;

import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.SWT;
import org.eclipse.swt.accessibility.AccessibleAdapter;
import org.eclipse.swt.accessibility.AccessibleEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;

import commons.utils.facades.DialogConstantsFacade;
import commons.utils.facades.ProgramFacade;

/**
 * Message dialog with hyperlink message
 * 
 * @author A Kunin
 */
public class MessageDialogWithHyperlink extends MessageDialog {
    private Link _link;
    private final String[] _hyperlink;
    private final String[] _dialogMessage;

    /**
     * 
     * @param parentShell
     * @param dialogTitle
     * @param dialogTitleImage
     * @param dialogMessage
     * @param hyperlink
     * @param dialogImageType
     * @param dialogButtonLabels
     * @param defaultIndex
     */
    public MessageDialogWithHyperlink(Shell parentShell, String dialogTitle, Image dialogTitleImage, String[] dialogMessage,
	    String[] hyperlink, int dialogImageType, String[] dialogButtonLabels, int defaultIndex) {
	super(parentShell, dialogTitle, dialogTitleImage, "", dialogImageType, dialogButtonLabels, defaultIndex);
	_hyperlink = hyperlink;
	_dialogMessage = dialogMessage;
    }

    @Override
    protected Control createMessageArea(Composite composite) {
	Image image = getImage();
	if (image != null) {
	    imageLabel = new Label(composite, SWT.NULL);
	    image.setBackground(imageLabel.getBackground());
	    imageLabel.setImage(image);
	    addAccessibleListeners(imageLabel, image);
	    GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.BEGINNING).applyTo(imageLabel);
	}
	// create message
	_link = new Link(composite, SWT.READ_ONLY);
	if (_dialogMessage != null && _hyperlink != null && _hyperlink.length == _dialogMessage.length) {
	    for (int i = 0; i < _dialogMessage.length; i++) {
		String txt = _dialogMessage[i];// != null ? _dialogMessage[i] :
					       // "";
		String link = _hyperlink[i];
		if (message == null) {
		    if (txt != null && link != null) {
			message = "<a href=\"" + link + "\">" + txt + "</a>";
		    } else if (txt != null) {
			message = txt;
		    }
		} else {
		    if (txt != null && link != null) {
			message += " <a href=\"" + link + "\">" + txt + "</a>";
		    } else if (txt != null) {
			message = " " + txt;
		    }
		}
	    }
	    if (message != null) {
		_link.setText(message);
		_link.addListener(SWT.Selection, new Listener() {
		    @Override
		    public void handleEvent(Event event) {
			ProgramFacade.getDefault().launch(event.text);
		    }
		});
		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.BEGINNING).grab(true, false)
			.hint(convertHorizontalDLUsToPixels(IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH), SWT.DEFAULT)
			.applyTo(_link);
	    }
	}
	return composite;
    }

    private void addAccessibleListeners(Label label, final Image image) {
	label.getAccessible().addAccessibleListener(new AccessibleAdapter() {
	    @Override
	    public void getName(AccessibleEvent event) {
		final String accessibleMessage = getAccessibleMessageFor(image);
		if (accessibleMessage == null) {
		    return;
		}
		event.result = accessibleMessage;
	    }
	});
    }

    private String getAccessibleMessageFor(Image image) {
	if (image.equals(getErrorImage())) {
	    return JFaceResources.getString("error");//$NON-NLS-1$
	}

	if (image.equals(getWarningImage())) {
	    return JFaceResources.getString("warning");//$NON-NLS-1$
	}

	if (image.equals(getInfoImage())) {
	    return JFaceResources.getString("info");//$NON-NLS-1$
	}

	if (image.equals(getQuestionImage())) {
	    return JFaceResources.getString("question"); //$NON-NLS-1$
	}

	return null;
    }

    /**
     * @see Dialog#createDialogArea(Composite)
     */
    @Override
    protected Control createDialogArea(Composite parent) {
	Composite dialogAreaComposite = (Composite) super.createDialogArea(parent);
	return dialogAreaComposite;
    }

    /**
     * Convenience method to open a standard error dialog.
     * 
     * @param parent
     *            the parent shell of the dialog, or <code>null</code> if none
     * @param title
     *            the dialog's title, or <code>null</code> if none
     * @param message
     *            the message
     */
    public static void openError(Shell parent, String title, String[] message, String[] hyperlink) {
	if (message != null) {
	    MessageDialogWithHyperlink dialog = new MessageDialogWithHyperlink(parent, title, null, message, hyperlink, ERROR,
		    new String[] { DialogConstantsFacade.getOkLabel() }, 0);
	    dialog.open();
	}
	return;
    }

    /**
     * Convenience method to open a standard information dialog.
     * 
     * @param parent
     *            the parent shell of the dialog, or <code>null</code> if none
     * @param title
     *            the dialog's title, or <code>null</code> if none
     * @param message
     *            the message
     */
    public static void openInformation(Shell parent, String title, String[] message, String[] hyperlink) {
	MessageDialogWithHyperlink dialog = new MessageDialogWithHyperlink(parent, title, null, message, hyperlink,
		INFORMATION, new String[] { DialogConstantsFacade.getOkLabel() }, 0);
	dialog.open();
	return;
    }

    /**
     * Convenience method to open a standard warning dialog.
     * 
     * @param parent
     *            the parent shell of the dialog, or <code>null</code> if none
     * @param title
     *            the dialog's title, or <code>null</code> if none
     * @param message
     *            the message
     * @param hyperlink
     */
    public static void openWarning(Shell parent, String title, String[] message, String[] hyperlink) {
	MessageDialogWithHyperlink dialog = new MessageDialogWithHyperlink(parent, title, null, message, hyperlink, WARNING,
		new String[] { DialogConstantsFacade.getOkLabel() }, 0);
	dialog.open();
	return;
    }

    public Link getLink() {
	return _link;
    }

    @Override
    public Button getButton(int index) {
	return super.getButton(index);
    }

    public void runEventLoop() {
	// Use the display provided by the shell if possible
	Display display;
	Shell shell = getShell();
	if (shell == null) {
	    display = Display.getCurrent();
	} else {
	    display = shell.getDisplay();
	}

	while (shell != null && !shell.isDisposed()) {
	    if (!display.readAndDispatch()) {
		display.sleep();
	    }
	}
	display.update();
    }
}
